﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using YiNing.UI.Controls;

namespace YiNing.Tools
{
    public partial class NonstandardMappingForm : Form
    {
        public class TestProgramConfig
        {
            /// <summary>
            /// 输出脉冲宽度，也就是光源的亮度
            /// </summary>
            public int OutputPulseWidth { get; set; }
            public string Name { get; set; }

            /// <summary>
            /// 晶圆的编号信息
            /// </summary>
            public string Id { get; set; }
            public double DieWidth { get; set; }
            public double DieHeight { get; set; }
            /// <summary>
            /// 两个die的间隔X
            /// </summary>
            public double DieIntervalX { get; set; }
            /// <summary>
            /// 两个die的间隔Y
            /// </summary>
            public double DieIntervalY { get; set; }
            public int BestZPulseMain { get; set; }
            public double BestZPulseMainSensor { get; set; }
            public int[] BestZPulses = new int[6];  // 所有物镜的最佳高度
            public Die[,] Mapping { get; set; }

            /// <summary>
            /// 排除边沿芯片的个数
            /// </summary>
            public int ExcludeEdgeNum { get; set; }

            /// <summary>
            /// 晶圆的半径
            /// </summary>
            public double WaferRadius { get; set; }
            /// <summary>
            /// 切割道像素宽度
            /// </summary>
            public double CutRoadWidthPixel { get; set; }
            /// <summary>
            /// 切割道宽度微米
            /// </summary>
            public double CutRoadWidth { get; set; }
            //晶圆中心
            public Point WaferCenter { get; set; }
            /// <summary>
            /// 晶圆的厚度
            /// </summary>
            public double WaferThickness { get; set; }
            /// <summary>
            /// Die的总数
            /// </summary>
            public int DieCount { get; set; }

        }


        [DllImport("user32")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, IntPtr lParam);
        private const int WM_SETREDRAW = 0xB;
        /// <summary>
        /// 重写CreateParams方法
        /// 解决控件过多加载闪烁问题
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;//用双缓冲绘制窗口的所有子控件
                return cp;
            }
        }

        public NonstandardMappingForm()
        {
            InitializeComponent();

            nonstandardWafermap1.OnDieClick += NonstandardWafermap1_OnDieClick;
        }

        private List<Die> trainDies = new List<Die>();
        private void NonstandardWafermap1_OnDieClick(object sender, Die e)
        {
            Control c = (Control)sender;
            //MessageBox.Show(c.Tag.ToString());
            if (trainDies.Find(v => v.XPluse == e.XPluse && v.YPluse == e.YPluse) == null)
            {
                e.ColorIndex = 2;
                trainDies.Add(e);
            }
            else
            {
                e.ColorIndex = 1;
                trainDies.Remove(e);
            }
            this.Text = trainDies.Count.ToString();

            YiningImage yiningImage = new YiningImage(300000, 300000);

            yiningImage.DrawCircle(nonstandardWafermap1.WaferMinX, nonstandardWafermap1.WaferMaxY, nonstandardWafermap1.WaferRadius * 2, nonstandardWafermap1.WaferRadius * 2);


            Point lt = e.GetDieRectLeftTopPoint(true, 1, 1, 7808, 9400);
            Point rb = e.GetDieRectRightBottomPoint(true, 1, 1, 7808, 9400);

            Point lb = new Point(Convert.ToInt32(e.GetDieRectLeftBottomPoint(true, 1, 1, 7808, 9400).X + nonstandardWafermap1.WaferMinX),Convert.ToInt32(e.GetDieRectLeftBottomPoint(true, 1, 1, 7808, 9400).Y + nonstandardWafermap1.WaferMinY));
            Point rt = new Point(Convert.ToInt32(e.GetDieRectRightTopPoint(true, 1, 1, 7808, 9400).X + nonstandardWafermap1.WaferMinX), Convert.ToInt32(e.GetDieRectRightTopPoint(true, 1, 1, 7808, 9400).Y + nonstandardWafermap1.WaferMinY));
            yiningImage.DrawRectleByLeftBottomAndRightTop(lb, rt);
            yiningImage.Save(@"D:\QTWaferProgram\384\test\1.jpg");
            //yiningImage.DrawRectleByLeftTopAndRightBottom(lt, rb, new Pen(Color.Green, 10));
            //yiningImage.Save(@"D:\QTWaferProgram\384\test\2.jpg");

        }

        private void loadMappingProgram()
        {
            string filePath2;
            OpenFileDialog fileDialog2 = new OpenFileDialog();
            fileDialog2.Title = "请选择图谱文件";
            fileDialog2.Filter = "所有文件|*.*";
            fileDialog2.RestoreDirectory = false;    //若为false，则打开对话框后为上次的目录。若为true，则为初始目录
            if (fileDialog2.ShowDialog() == DialogResult.OK)
            {
                filePath2 = Path.GetFullPath(fileDialog2.FileName);
                var programConfig = JsonHelper.DeserializeByFile<TestProgramConfig>(filePath2);
                nonstandardWafermap1.SetWaferInfo(programConfig.WaferCenter, programConfig.WaferRadius);
            }
            fileDialog2.Dispose();
        }

        /// <summary>
        /// 加载图谱
        /// </summary>
        private void loadMapping()
        {
            string filePath2;
            OpenFileDialog fileDialog2 = new OpenFileDialog();
            fileDialog2.Title = "请选择图谱文件";
            fileDialog2.Filter = "所有文件|*.*";
            fileDialog2.RestoreDirectory = false;    //若为false，则打开对话框后为上次的目录。若为true，则为初始目录
            if (fileDialog2.ShowDialog() == DialogResult.OK)
            {
                filePath2 = Path.GetFullPath(fileDialog2.FileName);
                var data = JsonHelper.DeserializeByFile<List<Die>>(filePath2);
                //nonstandardWafermap1.Colors = Die.DefaultColors;

                //var data = JsonHelper.DeserializeByFile<List<Die>>(@"D:\QTWaferProgram\test\result_mapping.txt");
                nonstandardWafermap1.Dataset = data;//JsonHelper.DeserializeByFile<List<Die>>(@"C:\Users\Administrator\Downloads\384\nonstandardMapping.zyn");
                nonstandardWafermap1.Notchlocation = 90;
                //lbAllDiesNum.Text = waferMap.DieAllNum.ToString();
                //lbOkDiesNum.Text = waferMap.DieOkNum.ToString();
                //lbNgDiesNum.Text = waferMap.DieNgNum.ToString();
                nonstandardWafermap1.BringToFront();
                //waferMap.Dataset = data;
                //waferMap.Notchlocation = 90;
                ////wmap.MinimumSize = new Size(500, 500);
                //waferMap.Interactive = true;
                nonstandardWafermap1.NotcheOrFlat = UI.Config.Enums.TraitType.Notch;
                //waferMap.SelectX = 150;
                //waferMap.SelectY = 180;
                //waferMap.SelectOneDie = data[21, 14];
            }
            fileDialog2.Dispose();
            //Die[,] dies = 
        }


        public void range()
        {
            List<Die> dies = new List<Die>();
            foreach (var die in nonstandardWafermap1.Dataset)
            {
                //die.OffsetWaferCenterYPulse -= 9720 / 2;
                //die.YPluse -= 9720 / 2;
                //dies.Add(die);
                ////Size dieSize = die.GetDieSize();

                ////if (dieSize.Width>8500)
                ////{
                ////    dies.Add(die);
                ////}
            }

            JsonHelper.Serialize(dies, @"D:\QTWaferProgram\384\big-----a.zyn");
        }
        private void Button_Click(object sender, EventArgs e)
        {
            DarkButton btn = sender as DarkButton;
            string type = btn.Text.ToString();
            switch (type)
            {
                case "加载图谱":
                    loadMapping();
                    break;
                case "加载晶圆边沿":
                    loadMappingProgram();
                    break;
                case "保存图谱":

                    break;
                case "轮询每个Die":

                    range();
                    break;
                case "计算飞牌行":
                    var dies = new ConcurrentQueue<Die>();
                    CalFlyLine(nonstandardWafermap1.Dataset, out dies);
                    break;
                case "添加":

                    Test();

                    break;

            }
        }

        private void Test()
        {
            Point LeftTopPoint = new Point(170300, 187481);
            Point RightBottomPoint = new Point(178109, 178081);

            int DieWidth = 7808;
            int DieHeight = 9400;
            int XDieNumber = 1;
            int YDieNumber = 1;
            if (nonstandardWafermap1.AddDiesByRect(nonstandardWafermap1.WaferCenter, LeftTopPoint, RightBottomPoint, nonstandardWafermap1.WaferRadius, DieWidth, DieHeight, XDieNumber, YDieNumber))
            {
            }
        }

        /// <summary>
        /// 计算飞牌行数据
        /// </summary>
        /// <param name="dieList">非标晶圆的数据,此处的芯片位置都是当前晶圆的位置都是准确的，所以不需要转换</param>
        /// <param name="dies"></param>
        /// <param name="isZ"></param>
        private List<TestFlyLine> CalFlyLine(List<Die> dieList, out ConcurrentQueue<Die> dies, bool isZ = true)
        {
            var flys = new List<TestFlyLine>();
            YiningImage yiningImage = new YiningImage(300000, 300000);
            dies = new ConcurrentQueue<Die>();
            var sortedDies = dieList.OrderByDescending(v => v.YPluse).ThenBy(v => v.XPluse).ToList();

            int n = 0;
            TestFlyLine oneLine = null;
            List<Die> currentDies = new List<Die>(); //当前@行@的@所有@die@
            for(int i = 0; i < sortedDies.Count; i++)
            {
                if ( i>0 &&(sortedDies[i-1].YPluse - sortedDies[i].YPluse) > sortedDies[i].GetDieSize().Height * 0.8) // 如果一个die的y坐标减去当前飞拍行的y大于（0.8*die的高度）的话那么就是下一行
                {

                    if (currentDies.Count > 0)
                    {
                        // 先X坐标排序计算该行最终的endX，然后再清空
                        currentDies = currentDies.OrderBy(v => v.XPluse).ToList();
                        oneLine = new TestFlyLine(currentDies[0].XPluse, currentDies[0].XPluse, currentDies[0].YPluse);
                        //理论上currentDies至少有一个，所以这里不考虑为0的情况
                        oneLine.EndX = currentDies[currentDies.Count - 1].XPluse;
                        oneLine.IntervalX = (oneLine.EndX - oneLine.StartX) / (currentDies.Count - 1);
                        flys.Add(oneLine);

                        if (n % 2 == 0)
                        {
                            for (int j = 0; j < currentDies.Count; j++)
                            {
                                dies.Enqueue(currentDies[j]);
                            }
                        }
                        else
                        {
                            for (int j = currentDies.Count -1; j >= 0; j--)
                            {
                                dies.Enqueue(currentDies[j]);
                            }
                        }
                        Console.WriteLine(currentDies.Count);
                        n++;
                        currentDies.Clear();
                    }
                    //yiningImage.DrawLine(oneLine.StartX, oneLine.EndX, oneLine.StartY, oneLine.StartY, 0);
                }

                currentDies.Add(sortedDies[i]); //
                yiningImage.DrawCircle(sortedDies[i].XPluse, sortedDies[i].YPluse, 5, 5);
                yiningImage.DrawString(i+"-" + sortedDies[i].YPluse +"_" + sortedDies[i].XPluse, sortedDies[i].GetDieRectLeftTopPoint(), 20);
            }
            currentDies = currentDies.OrderBy(v => v.XPluse).ToList();
            oneLine = new TestFlyLine(currentDies[0].XPluse, currentDies[0].XPluse, currentDies[0].YPluse);
            oneLine.EndX = currentDies[currentDies.Count - 1].XPluse;
            oneLine.IntervalX = (oneLine.EndX - oneLine.StartX) / (currentDies.Count - 1);
            flys.Add(oneLine);

            if (n % 2 == 0)
            {
                for (int j = 0; j < currentDies.Count; j++)
                {
                    dies.Enqueue(currentDies[j]);
                }
            }
            else
            {
                for (int j = currentDies.Count - 1; j >= 0; j--)
                {
                    dies.Enqueue(currentDies[j]);
                }
            }
            Console.WriteLine(currentDies.Count);
            currentDies.Clear();
            yiningImage.DrawLine(oneLine.StartX, oneLine.EndX, oneLine.StartY, oneLine.StartY, 0);
            yiningImage.Save("D:/aaaaa.jpg");


            for (int i = 0; i < flys.Count; i++) 
            {
                yiningImage.DrawLine(flys[i].StartX, flys[i].EndX, flys[i].StartY, flys[i].StartY, i % 2, new System.Drawing.Pen(System.Drawing.Color.Red, 30));
            }
            yiningImage.Save("D:/bbbb.jpg");

            yiningImage = new YiningImage(300000, 300000);

            int a = 0;
            while(dies.TryDequeue(out Die oo))
            {
                yiningImage.DrawCircle(oo.XPluse, oo.YPluse, 5, 5);
                yiningImage.DrawString(a + "-" + oo.YPluse + "_" + oo.XPluse, oo.GetDieRectLeftTopPoint(), 20);
                a++;
            }
            yiningImage.Save("D:/ccccccc.jpg");
            //dieList.OrderBy(v=>v.YIndex)

            return flys;
        }
    }
}
